/*
 * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project.
 * All rights reserved.
 * Project URL:https://github.com/JackJiang2011/beautyeye
 * Version 3.6
 *
 * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * BeautyEyeLNFHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang.
 * You can contact author with jb2011@163.com.
 */
package com.lijinjiang.beautyeye;

import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.border.Border;

import com.lijinjiang.beautyeye.utils.JVM;
import com.lijinjiang.beautyeye.widget.border.BEShadowBorder;
import com.lijinjiang.beautyeye.widget.border.BEShadowBorder3;
import com.lijinjiang.beautyeye.widget.border.PlainGrayBorder;

/**
 * <p>
 * BeautyEye Swing外观实现方案 - L&F核心辅助类.<br>
 * <p>
 * 项目托管地址：https://github.com/JackJiang2011/beautyeye
 * @author Jack Jiang(jb2011@163.com), 2012-05
 * @version 1.0
 */
public class BeautyEyeLNFHelper {
    /**
     * 开关量：用于开启/关闭BeautyEye LNF的调试信息输出.
     * <p>
     * 默认false，即不开启调试信息输出.
     * @since 3.2
     */
    public static boolean debug = false;
    /**
     * 开关量：用于开启/关闭当窗口（包括JFrame、JDialog）处于非活动
     * 状态（inactivity）时的半透明视觉效果.
     * <p>
     * 默认true，即表示默认开启半透明效果.
     * @since 3.2
     */
    public static boolean translucencyAtFrameInactive = true;

    /**
     * BeautyEye LNF 的窗口边框样式.
     * <p>默认值：运行在java1.6.0_u10及以上版本时使用 {@link FrameBorderStyle#translucencyAppleLike}，
     * 运行在java1.5版本时使用{@link FrameBorderStyle#generalNoTranslucencyShadow}.
     *
     * <p><b>注意：</b>如需设置本参数，请确保它在UIManager.setLookAndFeel前被设置，否则将不会起效哦.
     * @see FrameBorderStyle
     */
    public static FrameBorderStyle frameBorderStyle =
            isSupportedTranslucency() ? FrameBorderStyle.translucencyAppleLike : FrameBorderStyle.generalNoTranslucencyShadow;

    /**
     * 颜色全局变量：正常情况下的窗口文本颜色.
     * <p>
     * 你可设置本变量，也可直接通过{@code UIManager.put("activeCaptionText",new ColorUIResource(c))}和
     * {@code UIManager.put("inactiveCaptionText",new ColorUIResource(c))}来实现窗口文本颜色的改变.
     * <p>
     * 窗体不活动(inactivite)时的颜色将据此自动计算出来，无需额外设置.
     * 默认是黑色（new Color(0,0,0)）.
     */
    public static Color activeCaptionTextColor = new Color(0, 0, 0);//黑色

    /**
     * 颜色全局变量：多数组件的背景色.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是浅灰色（new Color(250,250,250)）.
     * @since 3.2
     */
    public static Color commonBackgroundColor = new Color(250, 250, 250);

    /**
     * 颜色全局变量：多数组件的前景色（文本颜色）.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是深灰色（new Color(60,60,60)）.
     * @since 3.2
     */
    public static Color commonForegroundColor = new Color(0, 0, 0);//102,102,102);
    /**
     * 颜色全局变量：某些组件的焦点边框颜色.
     * 当前主要用于按钮等焦点边框的绘制颜色.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是浅灰色（new Color(250,250,250)）.
     * @since 3.2
     */
    public static Color commonFocusedBorderColor = new Color(162, 162, 162);
    /**
     * 颜色全局变量：某些组件被禁用时的文本颜色.
     * 当前主要用于菜单项中.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是浅灰色（new Color(172,168,153)）.
     * @since 3.2
     */
    public static Color commonDisabledForegroundColor = new Color(172, 168, 153);
    /**
     * 颜色全局变量：多数组件中文本被选中时的背景色.当前主要用于各文本组件等.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是深灰色（new Color(2,129,216)）.
     * @since 3.2
     */
    public static Color commonSelectionBackgroundColor = new Color(2, 129, 216);

    /**
     * ComboBox 相关颜色
     */
    public static Color comboboxSelectionBackground = new Color(255, 255, 255);

    public static Color comboboxSelectionForeground = new Color(0, 0, 0);


    /**
     * JTable 被选中后的背景色
     */
    public static Color focusCellBackground = new Color(2, 129, 216);


    /**
     * 颜色全局变量：多数组件中文本被选中时的前景色（文本颜色）.当前主要用于各文本组件、菜单项等.
     * <p>
     * 你可设置本变量，也可直接通过各自的UIManager属性来改变它们.
     * <p>
     * 默认是深灰色（new Color(255,255,255)）.
     * @since 3.2
     */
    public static Color commonSelectionForegroundColor = new Color(255, 255, 255);

    /**
     * 开关量：用于默认设置或不设置窗口（Frame及其子类）的设置此窗体的最大化边界.
     * <p>
     * 此开关量是它是为了解决这样一个问题 ：<br>
     * 当不使用操作系统的窗口装饰（即使用完全自定义的窗口标题、边框）时，在windows上最
     * 大化窗口时将会全屏显示从而覆盖了下方的任务栏（task bar），这个问题 据说自2002年
     * 就已存在，SUN一直未解决或者根本不认为是bug。目前的解决方案是当本变量是true时则
     * 默认为每一个窗体设置最大化边界，否则保持系统默认。不过这样设置并非完美方案：一旦
     * 设置了最大边界，则此后无论Task Bar再怎么调 整大小，比如被hide了，则窗体永远是设
     * 置时的最大边界，不过目前也只能这么折中解决了，因为窗体最大化事件处理并非L&F中实现
     * ，暂未找到其它更好的方法。
     * <p>
     * 默认true，即表示默认开启此设置.
     * @see javax.swing.JFrame#setMaximizedBounds(java.awt.Rectangle)
     * @since 3.2
     */
    public static boolean setMaximizedBoundForFrame = true;

    /**
     * BeautyEye LNF的外观实现核心方法.
     * <p>
     * 本方法可以直接从外部调用，这意味着BeautyEye LNF的外观核心实现无需特定于LookAndFeel的实例.
     * <p>也就是说任意外观都可应用本方法所作的外观实现（并保证跨平台），以使之可灵活应用.
     * @see com.lijinjiang.beautyeye.ch1_titlepane.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch2_tab.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch3_button.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch_x.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch4_scroll.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch5_table.__UI__#uiReImpl()
     * @see com.lijinjiang.beautyeye.ch6_textcoms.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch7_popup.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch8_toolbar.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch9_menu.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch10_internalframe.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch12_progress.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch13_radio$cb_btn.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch14_combobox.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch15_slider.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch16_tree.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch17_split.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch18_spinner.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch19_list.__UI__#uiImpl()
     * @see com.lijinjiang.beautyeye.ch20_filechooser.__UI__#uiImpl_win()
     */
    protected static void implLNF() {
        //各种杂七杂八的设置
        com.lijinjiang.beautyeye.ch_x.__UI__.uiImpl();
        //自定义窗口的L&F实现
        com.lijinjiang.beautyeye.ch1_titlepane.__UI__.uiImpl();
        //自定义JTabbedPane的L&F实现
        com.lijinjiang.beautyeye.ch2_tab.__UI__.uiImpl();
        //自定义按钮的L&F实现
        com.lijinjiang.beautyeye.ch3_button.__UI__.uiImpl();
        //自定义滚动条的L&F实现
        com.lijinjiang.beautyeye.ch4_scroll.__UI__.uiImpl();
        //自定义表格头的L&F实现
        com.lijinjiang.beautyeye.ch5_table.__UI__.uiReImpl();
        //自定义文本组件的L&F实现
        com.lijinjiang.beautyeye.ch6_textcoms.__UI__.uiImpl();
        //自定义弹出组件（包括toolTip组件和弹出菜单等）的L&F实现
        com.lijinjiang.beautyeye.ch7_popup.__UI__.uiImpl();
        //自定义ToggleButton的L&F实现
        com.lijinjiang.beautyeye.ch8_toolbar.__UI__.uiImpl();
        //自定义菜单项的L&F实现
        com.lijinjiang.beautyeye.ch9_menu.__UI__.uiImpl();
        //自定义DesktopPane及内部窗体的L&F实现
        com.lijinjiang.beautyeye.ch10_internalframe.__UI__.uiImpl();
        //自定义进度条的L&F实现
        com.lijinjiang.beautyeye.ch12_progress.__UI__.uiImpl();
        //自定义单选按钮的L&F实现
        com.lijinjiang.beautyeye.ch13_radio$cb_btn.__UI__.uiImpl();
        //自定义下拉框的L&F实现
        com.lijinjiang.beautyeye.ch14_combobox.__UI__.uiImpl();
        //自定义JSlider的L&F实现
        com.lijinjiang.beautyeye.ch15_slider.__UI__.uiImpl();
        //自定义JTree的L&F实现
        com.lijinjiang.beautyeye.ch16_tree.__UI__.uiImpl();
        //自定义JSplitPane的L&F实现
        com.lijinjiang.beautyeye.ch17_split.__UI__.uiImpl();
        //自定义JSpinner的L&F实现
        com.lijinjiang.beautyeye.ch18_spinner.__UI__.uiImpl();
        //自定义JList的L&F实现
        com.lijinjiang.beautyeye.ch19_list.__UI__.uiImpl();
        //自定义JFileChooser的L&F实现
        com.lijinjiang.beautyeye.ch20_filechooser.__UI__.uiImpl();
        //自定义JFileChooser的L&F实现（为了解决JFileChooser中的文件查看列表的行高问题）
        com.lijinjiang.beautyeye.ch20_filechooser.__UI__.uiImpl_cross();
    }

    /**
     * Gets the beauty eye lnf str cross platform.
     * @return "com.lijinjiang.beautyeye.BeautyEyeLookAndFeelCross"
     */
    public static String getBeautyEyeLNFStrCrossPlatform() {
        return "com.lijinjiang.beautyeye.BeautyEyeLookAndFeelCross";
    }

    /**
     * Gets the beauty eye lnf str windows platform.
     * @return "com.lijinjiang.beautyeye.BeautyEyeLookAndFeelWin"
     */
    public static String getBeautyEyeLNFStrWindowsPlatform() {
        return "com.lijinjiang.beautyeye.BeautyEyeLookAndFeelWin";
    }

    /**
     * Gets the beauty eye lnf cross platform.
     * @return {@code new BeautyEyeLookAndFeelCross()}
     */
    public static LookAndFeel getBeautyEyeLNFCrossPlatform() {
        return new com.lijinjiang.beautyeye.BeautyEyeLookAndFeelCross();
    }

    /**
     * Gets the beauty eye lnf windows platform.
     * @return {@code new BeautyEyeLookAndFeelWin()}
     */
    public static LookAndFeel getBeautyEyeLNFWindowsPlatform() {
        return new com.lijinjiang.beautyeye.BeautyEyeLookAndFeelWin();
    }

    /**
     * 实施BeautyEye外观.<b>开发者使用BeautyEye L&F时应首选本方法.</b>
     * <p>
     * 本方法会据操作系统类型不同，来决定主类是使用BeautyEyeLookAndFeelWin还是BeautyEyeLookAndFeelWin.
     * 使用BeautyEye外观时推荐使用本方法来设置外观.之所以有平台不同主类不同的区分，是为了
     * 在Windows上平台上能更好的使用与操作系统相同的字体等设置.
     * @throws Exception {@link UIManager#setLookAndFeel(String)}过程中出现的任何异常
     * @see #getBeautyEyeLNFStrWindowsPlatform()
     * @see #getBeautyEyeLNFStrCrossPlatform()
     * @see com.lijinjiang.beautyeye.utils.Platform
     */
    public static void launchBeautyEyeLNF() throws Exception {
        if (com.lijinjiang.beautyeye.utils.Platform.isWindows()) {
            if (BeautyEyeLNFHelper.debug)
                System.out.println("已智能启用Windows平台专用的BeautyEye外观实现(您也可自行启用跨平台实现).");
            UIManager.setLookAndFeel(getBeautyEyeLNFStrWindowsPlatform());
        } else {
            if (BeautyEyeLNFHelper.debug)
                System.out.println("已智能启用跨平台的通用BeautyEye外观实现.");
            UIManager.setLookAndFeel(getBeautyEyeLNFStrCrossPlatform());
        }
    }

    /**
     * 当前运行的Java版本是否支持窗口透明、每像素半透明.
     * <p>
     * 必须java1.6.0_u12及以后版本才支持（为什么要到u12才支持？
     * 因u10、u11里的窗口透明存在BUG 6750920）.
     * @return true表示支持，否则不支持
     */
    public static boolean isSupportedTranslucency() {
        //是否支持窗口透明：必须java1.6.0_u12及以后版本才支持
        return JVM.current().isOneDotSixUpdate12OrAfter();//JDK1_6_U10);//为什么要到u12才支持？因u10里的窗口透明存在BUG 6750920
    }

    /**
     * <b>开发者无需关注本方法.</b>
     * <p>
     * true表示当前正在使用的窗口边框是不透明的，否则表示透明.
     * 本方法目前作为BERootPaneUI中设置窗口是否透明的开关使用.
     * <p>
     * #### 官方API中存的Bug： ####<br>
     * 在jdk1.6.0_u33下+win7平台下（其它版本是否也有这情况尚未完全验证），JFrame窗口
     * 被设置成透明后，该窗口内所有文本都会被反走样（不管你有没有要求反走样），真悲具。
     * 这应该是官方AWTUtilities.setWindowOpaque(..)bug导致的,1.7.0_u6同样存在该问题，
     * 使用BeautyEye时，遇到这样的问题只能自行使用本方法中指定的不透明边框才行（这样
     * BERootPaneUI类的设置窗口透明的代码就不用执行，也就不用触发该bug了），但JDialog
     * 不受此bug影响，诡异！
     * @return true, if successful
     * @since 3.2
     */
    public static boolean __isFrameBorderOpaque() {
        return frameBorderStyle == FrameBorderStyle.osLookAndFeelDecorated
                || frameBorderStyle == FrameBorderStyle.generalNoTranslucencyShadow;
    }

    /**
     * <b>开发者无需关注本方法.</b>
     * <p>
     * 根据设置的frameBorderStyle来返回正确的窗口边框.
     * @return 当 frameBorderStyle=={@link FrameBorderStyle#
     * defaultLookAndFeelDecorated}时返回无意义的 BorderFactory.createEmptyBorder()，
     * 否则返回指定边框对象
     */
    public static Border __getFrameBorder() {
        switch (frameBorderStyle) {
            case osLookAndFeelDecorated:
                return BorderFactory.createEmptyBorder();
            case translucencyAppleLike:
                return new BEShadowBorder3();
            case translucencySmallShadow:
                return new BEShadowBorder();
            case generalNoTranslucencyShadow:
            default:
                return new PlainGrayBorder();
        }
    }

    /**
     * BeautyEye LNF 的窗口边框样式.
     */
    public enum FrameBorderStyle {

        /**
         * 使用本地系统的窗口装饰样式（本样式将能带来最佳性能，使用操作系统默认窗口样式）.
         */
        osLookAndFeelDecorated,

        /**
         * 使用类似于MacOSX的强烈立体感半透明阴影边框（本样式性能尚可，视觉效果最佳）.
         */
        translucencyAppleLike,

        /**
         * 使用不太强烈立体感半透明阴影边框（本样式性能尚可，视觉效果较soft）.
         */
        translucencySmallShadow,
        /**
         * 使用不透明的普通边框（这是本LNF在Java1.5版默认使用的样式，因为java1.5不支持窗口透明）
         */
        generalNoTranslucencyShadow
    }

    /**
     * <b>开发者暂时无需关注此接口.</b>
     * <p>
     * 实现了此接口的UI类意味着用户可以通过自行设置诸如border等，来
     * 取消默认的 NinePatch 图实现的边框填充、背景填充等，具体设置哪
     * 些东西可以取消默认的NinePatch图填充的方式详见各自的类注释。
     */
    public interface __UseParentPaintSupported {

        /**
         * 是否使用父类的绘制实现方法，true表示是.
         * <p>
         * 因为在BE LNF中，进度条和背景都是使用N9图，比如没法通过设置JProgressBar的背景色和前景
         * 色来控制进度条的颜色，本方法的目的就是当用户设置了进度条的Background或Foreground
         * 时告之本实现类不使用BE LNF中默认的N9图填充绘制而改用父类中的方法（父类中的方法
         * 就可以支持颜色的设置罗，只是丑点，但总归是能适应用户的需求场景要求，其实用户完全可以
         * 通过JProgressBar.setUI(new MetalProgressBar())方式来自定义进度的UI哦）.
         * @return true, if is use parent paint
         */
        boolean isUseParentPaint();
    }
}
